﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Kinect;
using Coding4Fun.Kinect.Wpf;
using System.Windows.Threading;
using System.Timers;


namespace KinectFitness.MainMenu
{
    /// <summary>
    /// Interaction logic for Play.xaml
    /// </summary>
    public partial class Play : Page
    {
        public Play()
        {
            InitializeComponent();
            
        }
        
        //KinectSensor _sensor;
        bool closing;
        List<Point> points = new List<Point>();

        Dispatcher mainDispatcher = Dispatcher.CurrentDispatcher; 
        const int skeletonCount = 6;
        bool up;
        DateTime lastUpdate;
        Timer myTimer = new Timer(1000);
        int startTime = 35;
        Skeleton[] allSkeletons = new Skeleton[skeletonCount];
        int jacks = 0;

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            kinectSensorChooser1.KinectSensorChanged += new DependencyPropertyChangedEventHandler(kinectSensorChooser1_KinectSensorChanged);
            lblTimer.Content = "Time: " + startTime.ToString();
            myTimer.Elapsed +=new ElapsedEventHandler(myTimer_Elapsed);
            myTimer.Enabled = true;
           
        }

        private void myTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            mainDispatcher.BeginInvoke(DispatcherPriority.Background, new System.Threading.ThreadStart(delegate()
            {
                
                startTime--;
                if (jacks >= 5)
                {
                    myTimer.Enabled = false;
                    MessageBox.Show("nice job!");
                    Exercises e1 = new Exercises();
                    NavigationService.GetNavigationService(this).Navigate(e1);

                }
                lblTimer.Content = "Time: " + startTime.ToString();
                if (startTime == 0) {
                    myTimer.Enabled = false;
                    if (jacks < 5)
                    {
                        MessageBox.Show("Sorry, you didn't do enough, try again");
                        Exercises e1 = new Exercises();
                        NavigationService.GetNavigationService(this).Navigate(e1);

                    }
                    else
                    {
                        MessageBox.Show("nice job!");
                        Exercises e1 = new Exercises();
                        NavigationService.GetNavigationService(this).Navigate(e1);
                    }

                }

            }));
           
        }
        
        Skeleton GetFirstSkeleton(AllFramesReadyEventArgs e)
        {
            using (SkeletonFrame skeletonFrameData = e.OpenSkeletonFrame())
            {
                if (skeletonFrameData == null)
                {
                    return null;
                }

                skeletonFrameData.CopySkeletonDataTo(allSkeletons);

                Skeleton first = (from s in allSkeletons
                                  where s.TrackingState == SkeletonTrackingState.Tracked
                                  select s).FirstOrDefault();

                return first;
            }
        }

        void _sensor_AllFramesReady(object sender, AllFramesReadyEventArgs e)
        {
            
            
          
            if (closing)
            {
                return;
            }

            Skeleton first = GetFirstSkeleton(e);
            if (first == null)
            {
                return;
            }
            
            ScalePosition(leftEllipse, first.Joints[JointType.ShoulderCenter]);
            ScalePosition(rightEllipse, first.Joints[JointType.HipCenter]);
            GetCameraPoint(first,e);
            if (lastUpdate.AddSeconds(.5) <= DateTime.Now)
            {
                if (CheckCollision(leftEllipse, image1) && CheckCollision(rightEllipse, image1) && !up)
                {
                    jacks++;
                    up = true;
                    lblCount.Content = "Jumping Jacks: " + jacks.ToString();
                }
                else if (CheckCollision(leftEllipse, image1) && CheckCollision(rightEllipse, image1) && up)
                {
                    up = false;
                }
            }
        }

        private void ScalePosition(FrameworkElement element, Joint joint)
        {
            
            //convert the value to X/Y
            //Joint scaledJoint = joint.ScaleTo(1280, 720); 
            
            //convert & scale (.3 = means 1/3 of joint distance)
            
            Joint scaledJoint = joint.ScaleTo(1280, 720, .3f, .3f);

            Canvas.SetLeft(element, scaledJoint.Position.X);
            Canvas.SetTop(element, scaledJoint.Position.Y);
           
   
        }

        void stopKinect(KinectSensor sensor)
        {
            if (sensor != null)
            {
                sensor.Stop();
                sensor.AudioSource.Stop();

            }
        }

        private bool CheckCollision(FrameworkElement ctl1, FrameworkElement ctl2)
        {
            bool retval = false;
            Point ptTopLeft = new Point(Convert.ToDouble(ctl1.GetValue(Canvas.LeftProperty)), Convert.ToDouble(ctl1.GetValue(Canvas.TopProperty)));
            Point ptBottomRight = new Point(Convert.ToDouble(ctl1.GetValue(Canvas.LeftProperty)) + ctl1.Width, Convert.ToDouble(ctl1.GetValue(Canvas.TopProperty)) + ctl1.Height);
            Rect r1 = new Rect(ptTopLeft, ptBottomRight);

          

            Point ptTopLeft2 = new Point(Convert.ToDouble(ctl2.GetValue(Canvas.LeftProperty)), Convert.ToDouble(ctl2.GetValue(Canvas.TopProperty)));
            Point ptBottomRight2 = new Point(Convert.ToDouble(ctl2.GetValue(Canvas.LeftProperty)) + ctl2.Width, Convert.ToDouble(ctl2.GetValue(Canvas.TopProperty)) + ctl2.Height);
            Rect r2 = new Rect(ptTopLeft2, ptBottomRight2);

            r1.Intersect(r2);
            if (!r1.IsEmpty)
            {
                retval = true;
            }
            return retval;
        }


        void GetCameraPoint(Skeleton first, AllFramesReadyEventArgs e)
        {
           
          
            using (DepthImageFrame depth = e.OpenDepthImageFrame())
            {
                if (depth == null || kinectSensorChooser1.Kinect == null)
                {
                    return;
                }

                DepthImagePoint headDepthPoint = depth.MapFromSkeletonPoint(first.Joints[JointType.Head].Position);
                DepthImagePoint leftDepthPoint = depth.MapFromSkeletonPoint(first.Joints[JointType.HandLeft].Position);
                DepthImagePoint rightDepthPoint = depth.MapFromSkeletonPoint(first.Joints[JointType.HandRight].Position);
                DepthImagePoint hipDepthPoint = depth.MapFromSkeletonPoint(first.Joints[JointType.HipCenter].Position);
                DepthImagePoint shoulderDepthPoint = depth.MapFromSkeletonPoint(first.Joints[JointType.ShoulderCenter].Position);
                ColorImagePoint hipColorPoint = depth.MapToColorImagePoint(hipDepthPoint.X, hipDepthPoint.Y, ColorImageFormat.RgbResolution640x480Fps30);
                ColorImagePoint shoulderColorPoint = depth.MapToColorImagePoint(shoulderDepthPoint.X, shoulderDepthPoint.Y,ColorImageFormat.RgbResolution640x480Fps30);
                ColorImagePoint headColorPoint = depth.MapToColorImagePoint(headDepthPoint.X, headDepthPoint.Y, ColorImageFormat.RgbResolution640x480Fps30);
                ColorImagePoint leftColorPoint = depth.MapToColorImagePoint(leftDepthPoint.X, leftDepthPoint.Y, ColorImageFormat.RgbResolution640x480Fps30);
                ColorImagePoint rightColorPoint = depth.MapToColorImagePoint(rightDepthPoint.X, rightDepthPoint.Y, ColorImageFormat.RgbResolution640x480Fps30);
                CameraPosition(leftEllipse, leftColorPoint);
                CameraPosition(rightEllipse, rightColorPoint);
               
            }

        }

        void CameraPosition(FrameworkElement element,ColorImagePoint point)
        {
         
            Canvas.SetLeft(element, point.X - element.Width / 2);
            Canvas.SetTop(element, point.Y - element.Height / 2);
            
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            stopKinect(kinectSensorChooser1.Kinect);
        }

        private void kinectSensorChooser1_KinectSensorChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            KinectSensor oldSensor = (KinectSensor)e.OldValue;
            stopKinect(oldSensor);
            KinectSensor newSensor = (KinectSensor)e.NewValue;
            
           
            if (newSensor == null)
            {
                return;
            }
            var parameters = new TransformSmoothParameters
            {
                Smoothing = 0.3f,
                Correction = 0.0f,
                Prediction = 0.0f,
                JitterRadius = 1.0f,
                MaxDeviationRadius = 0.5f
            };
            newSensor.SkeletonStream.Enable(parameters);
            newSensor.SkeletonStream.Enable();
            newSensor.AllFramesReady += new EventHandler<AllFramesReadyEventArgs>(_sensor_AllFramesReady);
            newSensor.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);
            newSensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
           
            
            try
            {
                newSensor.Start();
            }
            catch (IOException)
            {

               kinectSensorChooser1.AppConflictOccurred();
            }    
        }

      
    }
}
